package io.gitee.kotle.android.utils

/**
 * 忽略错误,默认不提示异常
 */
inline fun <T> ignoreError(
    errorBlock: ((Throwable) -> T?) = { null },
    finallyBlock: (() -> Unit) = {},
    block: () -> T?
): T? {
    return try {
        block.invoke()
    } catch (e: Throwable) {
        printStackTrace { e }
        errorBlock.invoke(e)
    } finally {
        finallyBlock.invoke()
    }
}

/**
 * 忽略错误,返回true或者false
 */
inline fun ignoreErrorBoolean(
    errorBlock: ((Throwable) -> Boolean) = { false },
    finallyBlock: (() -> Unit) = {},
    block: () -> Unit
): Boolean {
    return try {
        block.invoke()
        true
    } catch (e: Throwable) {
        printStackTrace { e }
        errorBlock.invoke(e)
    } finally {
        finallyBlock.invoke()
    }
}

/**
 * 运行任务，可以设置重试次数
 */
inline fun <T> loopBlock(
    maxRunCount: Int = 3,
    breakCondition: (T?) -> Boolean = {
        //当返回true，或者运行次数超过最大值，则结束循环
        it != null
    },
    block: (Int/*当前循环次数*/) -> T?
): T? {
    var result: T? = null
    var runTimes = 0
    while (!breakCondition.invoke(result) && runTimes < maxRunCount) {
        result = block.invoke(runTimes)
        runTimes++
    }
    return result
}

/**
 * 异常捕获工具类
 */
class TryCatch<R>(private val block: () -> R?) {
    private var errorBlock: Function1<Throwable, R?>? = null
    private var finallyBlock: Function0<Unit>? = null

    fun start(): R? {
        return try {
            getRunBlock().invoke()
        } catch (e: Throwable) {
            printStackTrace { e }
            getCatchBlock()?.invoke(e)
        } finally {
            getFinallyBlock()?.invoke()
        }
    }

    /**
     * 获取代码允许的回调
     */
    fun getRunBlock() = block

    /**
     * catch 处理
     */
    fun getCatch(errorBlock: Function1<Throwable, R?>): TryCatch<R> {
        this.errorBlock = errorBlock
        return this
    }

    /**
     * catch 处理 回调
     */
    fun getCatchBlock() = errorBlock

    /**
     * finally处理
     */
    fun getFinally(finallyBlock: Function0<Unit>): TryCatch<R> {
        this.finallyBlock = finallyBlock
        return this
    }

    /**
     * finally处理 回调
     */
    fun getFinallyBlock() = finallyBlock
}

/**
 * 异常捕获代码块，如果需要捕获error或者Finally，请使用[TryCatch]，并且记得调用start()
 */
fun <R> tryCatch(block: () -> R?) = TryCatch(block).start()

